/*
 * @描述:  渲染对应input组件
 * @Author: /songzi
 * @Date: 2019-07-10 16:15:04
 * @Last Modified by: songzi
 * @Last Modified time: 2020-03-19 18:54:42
 */

import React from 'react';
// import { generate as generateId } from 'shortid';
import { Input, InputNumber, DatePicker, Select, Divider, Radio, Checkbox, Col, Row, AutoComplete } from 'antd';
import TreeTransfer from './TreeTransfer';

const { MonthPicker, RangePicker, WeekPicker } = DatePicker;

const { Option, OptGroup } = Select;
/**
 * @description 根据配置项类型渲染input类型
 * @param {Object} inputConfig input配置项
 * @returns
 */
const RenderInputType = inputConfig => {
  const {
    type,
    placeholder = '',
    optionValue,
    optionName,
    max,
    min,
    format,
    optionList,
    radioList,
    checkboxList,
    layout,
    dataSource,
    showSearch,
    optionFilterProp,
    filterOption,
    tokenSeparators,
    mode,
    inputProps = {}
  } = inputConfig;
  let moreProps;

  switch (type) {
    case 'input':
      return <Input placeholder={placeholder} {...inputProps} />;
    case 'autoComplete':
      return (
        <AutoComplete
          placeholder={placeholder}
          dataSource={dataSource}
          filterOption={(inputValue, option) => option.props.children.toUpperCase().indexOf(inputValue.toUpperCase()) !== -1}
          {...inputProps}
        />
      );
    case 'textarea':
      return <Input.TextArea placeholder={placeholder} {...inputProps} />;
    case 'select':
      moreProps = { ...inputProps };
      if (showSearch) moreProps.showSearch = showSearch;
      if (optionFilterProp) moreProps.optionFilterProp = optionFilterProp;
      if (filterOption) moreProps.filterOption = filterOption;
      if (tokenSeparators) moreProps.tokenSeparators = tokenSeparators;
      if (mode) moreProps.mode = mode;
      if (moreProps.mode === 'tags') moreProps.dropdownClassName = 'joy_multiple_select';
      return (
        <Select {...moreProps} placeholder={placeholder}>
          {getOptions(inputProps.value, optionList, optionValue, optionName)}
        </Select>
      );
    case 'inputNumber':
      return <InputNumber max={max} min={min} {...inputProps}></InputNumber>;
    case 'datePicker':
      return <DatePicker format={format} {...inputProps} />;
    case 'monthPicker':
      return <MonthPicker placeholder={placeholder} format={format} {...inputProps} />;
    case 'rangePicker':
      return <RangePicker format={format} {...inputProps} showTime />;
    case 'weekPicker':
      return <WeekPicker placeholder={placeholder} format={format} {...inputProps} />;
    case 'radio':
      return <Radio.Group>{mapRadiofromList(radioList)}</Radio.Group>;
    case 'checkbox':
      return <Checkbox.Group>{mapCheckBoxfromList(checkboxList, layout)}</Checkbox.Group>;
    case 'password':
      return <Input.Password placeholder={placeholder} {...inputProps}></Input.Password>;
    case 'treeTransfer':
      return <TreeTransfer dataSource={dataSource} {...inputProps}></TreeTransfer>;
    default:
      return <Input {...inputProps}></Input>;
  }
};

function getOptions(selectValues, optionList, optionValue, optionName) {
  if (optionList) {
    const filterOptions = { ...optionList };
    if (selectValues && selectValues instanceof Array) {
      filterOptions.list = optionList.list.filter(o => !selectValues.includes(o));
    }
    return mapOptionfromList(filterOptions);
  }
  return mapOption(optionValue, optionName);
}

/**
 * @description 遍历opthion配置
 * @author songs
 * @date 2019-07-10
 * @returns
 * @memberof RenderInputType
 */
function mapOption(optionValue = [], optionName = []) {
  const optionList = optionValue.map((item, index) => (
    <Option key={item.id || index} value={item}>
      {optionName[index] || item}
    </Option>
  ));
  return optionList;
}

/**
 * @description 解析对象形式至opthion渲染
 * @author songs
 * @date 2019-07-10
 * @returns
 * @memberof RenderInputType
 */
function mapOptionfromList(optObj = {}) {
  const { list = [], constList = [], name, value, gindex } = optObj;
  const $list = [...constList, ...list];
  const optionList = $list.map((item, index) => {
    const isGroup = Array.isArray(item);
    if (isGroup && item.length) {
      const { groupName } = item[0];
      const key = `group${index}`;
      return (
        <OptGroup key={key} label={groupName || `分组-${index}`}>
          {mapOptionfromList({ list: item, name, value, index })}
        </OptGroup>
      );
    }
    const $optName = item[name] || item.name || item;
    const $optValue = item[value] || item.value || item;
    return (
      <Option key={$optValue || `${gindex ? `${gindex}_` : ''}${index}`} value={$optValue}>
        {$optName}
      </Option>
    );
  });

  return optionList;
}

/**
 * @description 解析对象形式至Radio渲染
 * @author songs
 * @date 2019-07-10
 * @returns
 * @memberof RenderInputType
 */
function mapRadiofromList(optObj = {}) {
  const { list = [], name, value } = optObj;
  const radioList = list.map((item, index) => {
    const $optName = item[name] || item.name || '';
    const $optValue = item[value] || item.value || '';
    return (
      <Radio key={$optValue} value={$optValue}>
        {$optName}
      </Radio>
    );
  });
  return radioList;
}

/**
 * @description 解析json至checkbox渲染
 * @author songs
 * @date 2020-01-02
 * @param {*} [optObj={}]
 * @param {*} layout
 * @returns
 */
function mapCheckBoxfromList(optObj = {}, layout) {
  const { list = [], name, value } = optObj;
  const radioList = list.map((item, index) => {
    const $optName = item[name] || item.name || '';
    const $optValue = item[value] || item.value || '';
    const radioItem = (
      <Checkbox key={$optValue} value={$optValue}>
        {$optName}
      </Checkbox>
    );
    if (layout !== 'horizontal') {
      return radioItem;
    }
    return (
      <Col key={$optValue} span={24}>
        {radioItem}
      </Col>
    );
  });
  return layout !== 'horizontal' ? radioList : <Row>{radioList}</Row>;
}

/**
 * @description  解析option选项
 * @author songs
 * @date 2019-11-27
 * @param {*} optionList 选项数组
 * @param {*} valueFiled 值字段名称
 * @param {*} nameFiled name字段名称
 * @param {*} lable lable字段
 * @returns
 */
function renderOptions(optionList, valueFiled, nameFiled, lable) {
  const optionDomList = optionList.map((item, index) => {
    const keys = `option_${index}`;
    return (
      <Option lable={lable || `key${index}`} key={item.id || keys} value={item[valueFiled]}>
        {item[nameFiled] || item[valueFiled]}
      </Option>
    );
  });
  return optionDomList;
}

export { renderOptions };
export default RenderInputType;
